;
(function(factory) {
	if(typeof define === 'function' && define.amd) {
		define(['jquery', 'jquery.querybuilder-cn', 'bootstrap.table-cn', 'select2-cn'], factory);
	} else {
		if(typeof module === 'object' && module.exports) {
			//
		} else {
			factory(window.jQuery);
		}
	}
})(function($) {
	'use strict';
	var pluginName = "vw_query";
	var defaults = {
		$container: null,
		height: 0,
		heightDiff: 0,
		dataURL: "",
		queryURL: "",
		extrapara: {}
	};

	var methods = [
		'ajaxQueryData',
		'reset',
		'destroy'
	];

	var _calMethods = [{
		id: 0,
		text: "计数",
		fn: "COUNT"
	}, {
		id: 1,
		text: "总和",
		fn: "SUM"
	}, {
		id: 2,
		text: "平均值",
		fn: "AVG"
	}, {
		id: 3,
		text: "最大值",
		fn: "MAX"
	}, {
		id: 4,
		text: "最小值",
		fn: "MIN"
	}];

	var _methodtype = {
		"string": [1, 2, 3, 4],
		"integer": [0],
		"double": [0],
		"date": [1, 2, 3, 4],
		"time": [1, 2, 3, 4],
		"datetime": [1, 2, 3, 4],
		"boolean": [1, 2, 3, 4]
	};

	var _operators = {
		"string": ['equal', 'not_equal', 'begins_with', 'not_begins_with', 'contains', 'not_contains', 'ends_with', 'not_ends_with', 'is_empty', 'is_not_empty', 'between', 'not_between'],
		"integer": ['equal', 'not_equal', 'less', 'less_or_equal', 'greater', 'greater_or_equal', 'is_null', 'is_not_null'],
		"double": ['equal', 'not_equal', 'less', 'less_or_equal', 'greater', 'greater_or_equal', 'is_null', 'is_not_null'],
		"date": ['equal', 'not_equal', 'less', 'less_or_equal', 'greater', 'greater_or_equal', 'is_null', 'is_not_null'],
		"time": ['equal', 'not_equal', 'less', 'less_or_equal', 'greater', 'greater_or_equal', 'is_null', 'is_not_null'],
		"datetime": ['equal', 'not_equal', 'less', 'less_or_equal', 'greater', 'greater_or_equal', 'is_null', 'is_not_null'],
		"boolean": ['equal', 'not_equal', 'is_null', 'is_not_null'],
	};

	var vw_query = function(element, options) {
		this.$element = $(element);
		this.options = $.extend({}, defaults, options);
		this._defaults = defaults;
		this._name = pluginName + this.$element.attr('id');
		this.version = 'v1.0.0';
		this._init();
	}

	vw_query.prototype = {
		_init: function() {
			var that = this;
			var PANEL_ONE = [
				'<div class="panel panel-default">',
				'	<div class="panel-heading" role="tab">',
				'		<h4 class="panel-title">',
				'			<a class role="button" data-toggle="collapse" data-parent="#accordion" href="#collapse1">第一步：查看待分析的数据</a>',
				'		</h4>',
				'	</div>',
				'	<div id="collapse1" class="panel-collapse collapse in" role="tabpanel">',
				'		<div class="panel-body">',
				'			<table id="' + that._name + '-table-in"></table>',
				'		</div>',
				'	</div>',
				'</div>'
			].join("");

			var PANEL_TWO = [
				'<div class="panel panel-default">',
				'	<div class="panel-heading" role="tab">',
				'		<h4 class="panel-title">',
				'			<a class="collapsed" role="button" data-toggle="collapse" data-parent="#accordion" href="#collapse2">第二步：设置查询条件（若不需要基于查询结果进行汇总分析，则跳过此步骤，进行第三步）</a>',
				'		</h4>',
				'	</div>',
				'	<div id="collapse2" class="panel-collapse collapse" role="tabpanel">',
				'		<div class="panel-body">',
				'			<button id="' + that._name + '-resetfilter" class="btn btn-warning" data-target="basic"><i class="glyphicon glyphicon-refresh"></i> 重置条件</button>',
				'			<div id="' + that._name + '-querybuilder"></div>',
				'		</div>',
				'	</div>',
				'</div>'
			].join("");

			var PANEL_THREE = [
				'<div class="panel panel-default">',
				'	<div class="panel-heading" role="tab">',
				'		<h4 class="panel-title">',
				'			<a class="collapsed" role="button" data-toggle="collapse" data-parent="#accordion" href="#collapse3">第三步：设置汇总条件（若无需汇总，则跳过此步骤，进行第四步）</a>',
				'		</h4>',
				'	</div>',
				'	<div id="collapse3" class="panel-collapse collapse" role="tabpanel">',
				'		<div class="panel-body">',
				'			<form class="form-horizontal">',
				'				<div class="form-group">',
				'					<label class="col-md-2 control-label">分组字段: </label>',
				'					<div class="col-md-9">',
				'						<select id="' + that._name + '-GroupField" multiple="multiple" style="width: 100%;"></select>',
				'					</div>',
				'				</div>',
				'				<div class="form-group">',
				'					<label class="col-md-2 control-label">统计字段: </label>',
				'					<div class="col-md-3">',
				'						<select id="' + that._name + '-StatField" style="width: 100%;"></select>',
				'					</div>',
				'					<label class="col-md-2 control-label">统计方式: </label>',
				'					<div class="col-md-4">',
				'						<select id="' + that._name + '-CalMethod" multiple="multiple" style="width: 100%;"></select>',
				'					</div>',
				'				</div>',
				'			</form>',
				'		</div>',
				'	</div>',
				'</div>'
			].join("");

			var PANEL_FOUR = [
				'<div class="panel panel-default">',
				'	<div class="panel-heading" role="tab">',
				'		<h4 class="panel-title">',
				'			<a class="collapsed" role="button" data-toggle="collapse" data-parent="#accordion" href="#collapse4">第四步：查看分析结果</a>',
				'		</h4>',
				'	</div>',
				'	<div id="collapse4" class="panel-collapse collapse" role="tabpanel">',
				'		<div class="panel-body">',
				'			<button type="button" id="' + that._name + '-doquery" class="btn btn-warning"><i class="fa fa-search"></i> 查询</button>',
				'			<button type="button" id="' + that._name + '-exporttable" class="btn btn-success"><i class="fa fa-download"></i> 导出数据</button>',
				'			<button type="button" id="' + that._name + '-clear" class="btn btn-danger"><i class="fa fa-close"></i> 清除</button>',
				'			<button type="button" id="' + that._name + '-exportquery" class="btn btn-primary"><i class="fa fa-send"></i> 导出查询条件</button>',
				'			<div>',
				'				<table id="' + that._name + '-table-out"></table>',
				'			</div>',
				'		</div>',
				'	</div>',
				'</div>'
			].join("");

			this.$element.empty();
			this.$element.append([
				'<div class="row" style="margin-top:10px">',
				'		<div class="col-md-12">',
				'			<div class="panel-group" id="accordion" role="tablist">',
				PANEL_ONE,
				PANEL_TWO,
				PANEL_THREE,
				PANEL_FOUR,
				'			</div>',
				'		</div>',
				'</div>'
			].join(""));

			that.$tableIn = $('#' + that._name + '-table-in');
			that.$fnResetFilter = $('#' + that._name + '-resetfilter');
			that.$querybuilder = $('#' + that._name + '-querybuilder');
			that.$GroupField = $('#' + that._name + '-GroupField');
			that.$StatField = $('#' + that._name + '-StatField');
			that.$CalMethod = $('#' + that._name + '-CalMethod');
			that.$fnquery = $('#' + that._name + '-doquery');
			that.$fnexport = $('#' + that._name + '-exporttable');
			that.$fnclear = $('#' + that._name + '-clear');
			that.$fnexportquery = $('#' + that._name + '-exportquery');
			that.$tableOut = $('#' + that._name + '-table-out');

			that.$fnResetFilter.on('click', function() {
				that._resetfilter();
			});

			that.$fnquery.on('click', function() {
				that._doquery();
			});

			that.$fnexport.on('click', function() {
				that._exporttable();
			});

			that.$fnclear.on('click', function() {
				that._clear();
			});

			that.$fnexportquery.on('click', function() {
				that._exportquery();
			});

			that.$GroupField.select2({
				language: "zh-CN",
				allowClear: true,
				placeholder: '请选择...'
			});

			that.$StatField.select2({
				language: "zh-CN",
				allowClear: true,
				placeholder: '请选择...'
			});

			that.$CalMethod.select2({
				data: _calMethods,
				language: "zh-CN",
				placeholder: '请选择...'
			});
			that.$CalMethod.val(null).trigger('change');

			that.$StatField.on('select2:select', function(e) {
				that.$CalMethod.find('option').prop('disabled', false);
				that.$CalMethod.val(null).trigger('change');

				var thistype = _methodtype[that._head[e.params.data.id].type];
				for(var i = 0; i < thistype.length; i++) {
					$(that.$CalMethod[0][thistype[i]]).prop('disabled', true);
				}
				that.$CalMethod.select2();
			});

			that.$StatField.on('select2:unselect', function() {
				that.$CalMethod.find('option').prop('disabled', false);
				that.$CalMethod.val(null).trigger('change');
			});

			$('.panel-collapse').on('show.bs.collapse', function(e) {
				$.each($('.panel-collapse'), function(k, val) {
					var id = $(val).attr('id');
					if(id != $(e.target).attr('id')) {
						$('#' + id).collapse('hide');
					}
				});
			})

			resize();
			$(window).resize(resize);

			function resize() {
				var containerHeight;
				if(that.options.$container) {
					containerHeight = that.options.$container.height();
				} else {
					if(that.options.height) {
						containerHeight = that.options.height;
					} else {
						containerHeight = $(window).height();
					}
				}

				that.height = containerHeight - that.options.heightDiff;

				that.$tableIn.bootstrapTable('resetView', {
					"height": that.height / 2
				});
				that.$tableOut.bootstrapTable('resetView', {
					"height": that.height / 2
				});

				$(".fixed-table-container", that.$element).css('padding-bottom', 40 + "px");

				$('#collapse2').css({
					'overflow-y': 'auto',
					'max-height': that.height / 2 + 80 + "px"
				});
			}
		},

		_refresh: function() {
			$('#collapse1').collapse('show');
			$('#collapse2').collapse('hide');
			$('#collapse3').collapse('hide');
			$('#collapse4').collapse('hide');
		},

		_resetfilter: function() {
			try {
				this.$querybuilder.queryBuilder('reset');
			} catch(e) {};
		},

		_doquery: function() {
			var that = this;
			if(!that.options.queryURL || !that._queryTable) {
				return;
			}

			that.sql_select = "*";
			that.sql_where = "";
			that.sql_group = "";

			if(that.$StatField.val() != null && that.$CalMethod.val() != null) {
				var sel = [];
				var statval = that._head[that.$StatField.val()].name;
				var methodval = that.$CalMethod.select2('data');
				for(var i = 0; i < methodval.length; i++) {
					for(var j = 0; j < _calMethods.length; j++) {
						if(methodval[i].id == _calMethods[j].id) {
							sel[i] = _calMethods[j].fn + "(" + statval + ")";
							break;
						}
					}
				}
				that.sql_select = sel.join(",");
			}

			try {
				var sql = that.$querybuilder.queryBuilder('getSQL');
				that.sql_where = sql ? sql : "";
			} catch(e) {
				that._refresh();
				that._clear();
			}

			var groupval = that.$GroupField.val();
			if(groupval != null) {
				var group = [];
				for(var i = 0; i < groupval.length; i++) {
					group[i] = that._head[groupval[i]].name;
				}
				that.sql_group = group.join(",");
			}

			vw_common.customAjax({
				url: that.options.queryURL,
				type: "GET",
				dataType: "json",
				data: {
					"reportID": that._queryTable,
					"selectCondition": that.sql_select,
					"queryCondition": JSON.stringify(that.sql_where),
					"summaryCondition": that.sql_group
				}
			}, function(e) {
				for(var i = 0; i < e.data.head.columns.length; i++) {
					e.data.head.columns[i].sortable = true;
				};

				var rows = [];
				for(var i = 0; i < e.data.body.length; i++) {
					rows[i] = e.data.body[i].content;
				};

				that.$tableOut.bootstrapTable('destroy').bootstrapTable({
					"data": rows,
					"columns": e.data.head.columns,
					"height": that.height / 2,
					"pagination": true,
					"pageList": [10, 20, 30, 'All'],
					"locale": 'zh_CN',
					"showJumpto": true,
					"formatJumpto": function() {
						return '跳转';
					},
					"buttonsClass": "primary"
				});

				that.$tableOut.find('tr td,tr th').css({
					"text-align": "center",
					"white-space": "nowrap",
					"cursor": "default"
				});

			}, function() {
				that.$tableOut.bootstrapTable('destroy');
			});
		},

		_exporttable: function() {
			var that = this;
			var table = that.$tableOut[0];
			if(!table) {
				return;
			}
			require(['xlsx', 'FileSaver'], function() {
				var exportData = [];
				var filename = that._tableName ? that._tableName : new Date().getTime();
				var data = that.$tableOut.bootstrapTable('getData', false);
				var cols = that.$tableOut.bootstrapTable('getOptions').columns[0];

				$.each(data, function(k, val) {
					var exportRow = {};
					$.each(cols, function(i, col) {
						exportRow[col.title] = val[i];
					});
					exportData.push(exportRow);
				});

				const wopts = {
					bookType: 'xlsx',
					bookSST: false,
					type: 'binary'
				};

				const wb = {
					SheetNames: ['Sheet1'],
					Sheets: {},
					Props: {}
				};

				wb.Sheets['Sheet1'] = XLSX.utils.json_to_sheet(exportData);

				saveAs(new Blob([s2ab(XLSX.write(wb, wopts))], {
					type: "application/octet-stream"
				}), filename + '.' + (wopts.bookType == "biff2" ? "xls" : wopts.bookType));

				function s2ab(s) {
					if(typeof ArrayBuffer !== 'undefined') {
						var buf = new ArrayBuffer(s.length);
						var view = new Uint8Array(buf);
						for(var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
						return buf;
					} else {
						var buf = new Array(s.length);
						for(var i = 0; i != s.length; ++i) buf[i] = s.charCodeAt(i) & 0xFF;
						return buf;
					}
				}
			})
		},

		_clear: function() {
			this.$GroupField.val(null).trigger('change');
			this.$StatField.val(null).trigger('change');
			this.$CalMethod.val(null).trigger('change');
			this.$tableOut.bootstrapTable('destroy');
			try {
				this.$querybuilder.queryBuilder('reset');
			} catch(e) {};
		},

		_exportquery: function() {
			var that = this;
			var cont = {
				select: that.sql_select,
				where: that.sql_where,
				group: that.sql_group,
				table: that._queryTable,
				tableName: that._tableName
			};

			vw_static.downloadTextFile(JSON.stringify(cont), "[query]" + that._tableName + ".txt");

		},

		ajaxQueryData: function(table, tableName) {
			var that = this;
			if(!that.options.dataURL || !table) {
				return;
			}
			that._queryTable = table;
			that._tableName = tableName;
			that._refresh();
			that._clear();

			vw_common.customAjax({
				url: that.options.dataURL,
				type: "GET",
				dataType: "json",
				data: {
					"reportID": that._queryTable,
					"type": 1
				}
			}, function(e) {
				that._head = e.data.head.columns;
				for(var i = 0; i < that._head.length; i++) {
					that._head[i].sortable = true;
				};

				var rows = [];
				for(var i = 0; i < e.data.body.length; i++) {
					rows[i] = e.data.body[i].content;
				};

				that.$tableIn.bootstrapTable('destroy').bootstrapTable({
					"data": rows,
					"columns": that._head,
					"height": that.height / 2,
					"pagination": true,
					"pageList": [10, 20, 30, 'All'],
					"locale": 'zh_CN',
					"showJumpto": true,
					"formatJumpto": function() {
						return '跳转';
					},
					"buttonsClass": "primary"
				});

				that.$tableIn.find('tr td,tr th').css({
					"text-align": "center",
					"white-space": "nowrap",
					"cursor": "default"
				});

				var filters = [];
				for(var i = 0; i < that._head.length; i++) {
					filters.push({
						"id": that._head[i].name,
						"label": that._head[i].title,
						"type": that._head[i].type,
						"operators": _operators[that._head[i].type],
						"input": that._head[i].input,
						"values": that._head[i].values
					});
				}

				that.$querybuilder.queryBuilder('destroy');
				that.$querybuilder.queryBuilder({
					filters: filters
				});

				that.$StatField.empty();
				that.$GroupField.empty();
				for(var i = 0; i < that._head.length; i++) {
					that.$GroupField.append(new Option(that._head[i].title, i, false, false));
					that.$StatField.append(new Option(that._head[i].title, i, false, false));
				}
				that._clear;
			});
		},

		destroy: function() {
			this.$element.empty();
		},

		reset: function() {
			this._init();
		}
	}

	$.fn[pluginName] = function(option) {
		var value;
		var args = Array.prototype.slice.call(arguments, 1);

		this.each(function() {
			var $this = $(this);
			var data = $this.data(pluginName);

			if(typeof option === 'string') {

				if($.inArray(option, methods) < 0) {
					throw new Error("该方法不存在: " + option);
				}

				if(!data) {
					return;
				}

				value = data[option].apply(data, args);

				if(option === 'destroy') {
					$this.removeData(pluginName);
				}
			}

			if(!data) {
				$this.data(pluginName, (data = new vw_query(this, option)));
			}
		});

		return typeof value === 'undefined' ? this : value;
	};
});